using UniversalAdmin.Application.DTOs;
using UniversalAdmin.Domain.Entities;
using UniversalAdmin.Domain.Repositories;
using UniversalAdmin.Shared.Enums;

namespace UniversalAdmin.Application.Services;

public class DocumentPermissionService : IDocumentPermissionService
{
    private readonly IDocumentPermissionRepository _documentPermissionRepository;
    private readonly IDocumentRepository _documentRepository;
    private readonly IUserRepository _userRepository;
    private readonly IRoleRepository _roleRepository;

    public DocumentPermissionService(
        IDocumentPermissionRepository documentPermissionRepository,
        IDocumentRepository documentRepository,
        IUserRepository userRepository,
        IRoleRepository roleRepository)
    {
        _documentPermissionRepository = documentPermissionRepository;
        _documentRepository = documentRepository;
        _userRepository = userRepository;
        _roleRepository = roleRepository;
    }

    public async Task<DocumentPermissionDto> CreatePermissionAsync(CreateDocumentPermissionDto dto)
    {
        // 验证文档是否存在
        var document = await _documentRepository.GetByIdAsync(dto.DocumentId);
        if (document == null)
            throw new ArgumentException("文档不存在");

        // 验证用户或角色是否存在
        if (dto.PermissionType == PermissionType.UserBased && !await _userRepository.ExistsAsync(dto.UserId))
            throw new ArgumentException("用户不存在");

        if (dto.PermissionType == PermissionType.RoleBased && !await _roleRepository.ExistsAsync(dto.RoleId))
            throw new ArgumentException("角色不存在");

        // 检查是否已存在相同权限
        if (await _documentPermissionRepository.CheckPermissionExistsAsync(dto.DocumentId, dto.PermissionType, dto.UserId, dto.RoleId))
            throw new ArgumentException("该权限已存在");

        var permission = new DocumentPermission
        {
            DocumentId = dto.DocumentId,
            PermissionType = dto.PermissionType,
            UserId = dto.UserId,
            RoleId = dto.RoleId,
            CreatedAt = DateTime.UtcNow
        };

        await _documentPermissionRepository.AddAsync(permission);
        return MapToDto(permission);
    }

    public async Task<bool> DeletePermissionAsync(Guid id)
    {
        var permission = await _documentPermissionRepository.GetByIdAsync(id);
        if (permission == null)
            return false;

        await _documentPermissionRepository.DeleteAsync(permission);
        return true;
    }

    public async Task<bool> UpdatePermissionAsync(Guid id, UpdateDocumentPermissionDto dto)
    {
        var permission = await _documentPermissionRepository.GetByIdAsync(id);
        if (permission == null)
            return false;

        // 验证用户或角色是否存在
        if (dto.PermissionType == PermissionType.UserBased && !await _userRepository.ExistsAsync(dto.UserId))
            throw new ArgumentException("用户不存在");

        if (dto.PermissionType == PermissionType.RoleBased && !await _roleRepository.ExistsAsync(dto.RoleId))
            throw new ArgumentException("角色不存在");

        permission.PermissionType = dto.PermissionType;
        permission.UserId = dto.UserId;
        permission.RoleId = dto.RoleId;
        permission.UpdatedAt = DateTime.UtcNow;

        await _documentPermissionRepository.UpdateAsync(permission);
        return true;
    }

    public async Task<DocumentPermissionDto?> GetPermissionByIdAsync(Guid id)
    {
        var permission = await _documentPermissionRepository.GetByIdAsync(id);
        return permission != null ? MapToDto(permission) : null;
    }

    public async Task<IEnumerable<DocumentPermissionDto>> GetPermissionsByDocumentIdAsync(Guid documentId)
    {
        var permissions = await _documentPermissionRepository.GetByDocumentIdAsync(documentId);
        return permissions.Select(MapToDto);
    }

    public async Task<IEnumerable<DocumentPermissionDto>> GetPermissionsByUserIdAsync(Guid userId)
    {
        var permissions = await _documentPermissionRepository.GetByUserIdAsync(userId);
        return permissions.Select(MapToDto);
    }

    public async Task<IEnumerable<DocumentPermissionDto>> GetPermissionsByRoleIdAsync(Guid roleId)
    {
        var permissions = await _documentPermissionRepository.GetByRoleIdAsync(roleId);
        return permissions.Select(MapToDto);
    }

    public async Task<bool> CheckPermissionAsync(Guid documentId, Guid userId, PermissionType requiredPermission)
    {
        return await _documentPermissionRepository.CheckPermissionAsync(documentId, userId, requiredPermission);
    }

    public async Task<IEnumerable<Guid>> GetAccessibleDocumentIdsAsync(Guid userId, PermissionType requiredPermission)
    {
        return await _documentPermissionRepository.GetAccessibleDocumentIdsAsync(userId, requiredPermission);
    }

    public async Task DeletePermissionsByDocumentIdAsync(Guid documentId)
    {
        await _documentPermissionRepository.DeleteByDocumentIdAsync(documentId);
    }

    private DocumentPermissionDto MapToDto(DocumentPermission permission)
    {
        return new DocumentPermissionDto
        {
            Id = permission.Id,
            DocumentId = permission.DocumentId,
            PermissionType = permission.PermissionType,
            UserId = permission.UserId,
            RoleId = permission.RoleId,
            CreatedAt = permission.CreatedAt,
            UpdatedAt = permission.UpdatedAt
        };
    }
}